﻿using CSRedis;
using System.Threading.Tasks;

namespace ThresholdAssistant.Redis
{
    /// <summary>
    /// Redis客户端接口
    /// </summary>
    public interface IRedisClient
    {
        #region 同步操作
        /// <summary>
        /// 检查缓存Key是否存在
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        bool ContainsKey(string key);

        /// <summary>
        /// 批量删除缓存Key
        /// </summary>
        /// <param name="key"></param>
        /// <returns>删除成功的记录数量</returns>
        bool DeleteKey(string key);

        /// <summary>
        /// 批量删除缓存Key
        /// </summary>
        /// <param name="keys">key列表</param>
        /// <returns>删除成功的记录数量</returns>
        bool DeleteKey(params string[] keys);

        /// <summary>
        /// 重新命名key
        /// </summary>
        /// <param name="key">就的redis key</param>
        /// <param name="newKey">新的redis key</param>
        /// <returns></returns>
        bool RenameKey(string key, string newKey);

        /// <summary>
        /// 设置缓存过期
        /// </summary>
        /// <param name="key"></param>
        /// <param name="timeoutSeconds"></param>
        bool SetExpire(string key, int timeoutSeconds);

        /// <summary>
        /// 获取String类型的缓存
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        string StringGet(string key);

        /// <summary>
        /// 获取String类型的缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        T StringGet<T>(string key);

        /// <summary>
        /// 设置String类型缓存
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expireSeconds"></param>
        /// <returns></returns>
        bool StringSet(string key, string value, int expireSeconds = -1);

        /// <summary>
        /// 设置String类型缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expireSeconds"></param>
        /// <returns></returns>
        bool StringSet<T>(string key, T value, int expireSeconds = -1);

        /// <summary>
        /// 原子性递增
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value">增量：可以为负数</param>
        /// <param name="expireSeconds">缓存过期时间(单位：秒)</param>
        /// <returns>增长后的值</returns>
        long StringIncrement(string key, long value = 1, int expireSeconds = -1);


        /// <summary>
        /// 原子性递增
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value">增量：可以为负数</param>
        /// <returns>增长后的值</returns>
        long StringIncrementNoExpire(string key, long value = 1);

        /// <summary>
        /// 原子性递增 绝对过期时间
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value">增量：可以为负数</param>
        /// <param name="expireSeconds">过期时间</param>
        /// <returns>增长后的值</returns>
        long StringIncrementByAbsoluteExpire(string key, long value = 1, int expireSeconds = -1);

        /// <summary>
        /// 分布式锁
        /// </summary>
        /// <param name="key"></param>
        /// <param name="timeoutSeconds">缓存时间(单位：秒)</param>
        /// <param name="autoDelay">是否自动延迟</param>
        /// <returns></returns>
        CSRedisClientLock Lockup(string key, int timeoutSeconds = -1, bool autoDelay = true);

        /// <summary>
        /// 检查hash键是否存在
        /// </summary>
        /// <param name="key"></param>
        /// <param name="hashField"></param>
        /// <returns></returns>
        bool ContainsHashKey(string key, string hashField);

        /// <summary>
        /// 移除hash中的某值
        /// </summary>
        /// <param name="key"></param>
        /// <param name="hashField"></param>
        /// <returns></returns>
        bool DeleteHash(string key, string hashField);

        /// <summary>
        /// 移除hash中的某值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="hashFields"></param>
        /// <returns></returns>
        long DeleteHash(string key, params string[] hashFields);

        /// <summary>
        /// 获取Hash值
        /// </summary>
        /// <param name="key"></param>
        /// <param name="hashField"></param>
        /// <returns></returns>
        string HashGet(string key, string hashField);

        /// <summary>
        /// 获取Hash值
        /// </summary>
        /// <param name="key"></param>
        /// <param name="hashField"></param>
        /// <returns></returns>
        T HashGet<T>(string key, string hashField);

        /// <summary>
        /// 设置缓存
        /// </summary>
        /// <param name="key"></param>
        /// <param name="hashField"></param>
        /// <param name="value"></param>
        /// <param name="timeoutSeconds"></param>
        /// <returns></returns>
        bool HashSet(string key, string hashField, string value, int timeoutSeconds = -1);

        /// <summary>
        /// 设置缓存
        /// </summary>
        /// <param name="key"></param>
        /// <param name="hashField"></param>
        /// <param name="value"></param>
        /// <param name="timeoutSeconds"></param>
        /// <returns></returns>
        bool HashSet<T>(string key, string hashField, T value, int timeoutSeconds = -1);

        /// <summary>
        /// 原子性递增
        /// </summary>
        /// <param name="key"></param>
        /// <param name="hashField"></param>
        /// <param name="value">增量：可以为负数</param>
        /// <param name="timeoutSeconds">缓存过期时间（单位：秒）</param>
        /// <returns>增长后的值</returns>
        long HashIncrement(string key, string hashField, long value = 1, int timeoutSeconds = -1);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="timeoutSeconds"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        bool SetNx(string key, object value, int timeoutSeconds);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="timeoutSeconds"></param>
        /// <returns></returns>
        RedisClientLockNx LockNx(string key, int timeoutSeconds = 5);

        /// <summary>
        /// 分布式等待锁
        /// </summary>
        /// <param name="lockKey"></param>
        /// <param name="timeoutSeconds"></param>
        /// <param name="autoDelay">是否自动延长超时时间</param>
        /// <returns></returns>
        CSRedisClientLock Lock(string lockKey, int timeoutSeconds, bool autoDelay = false);

        /// <summary>
        /// 消息发布
        /// </summary>
        /// <param name="channel">频道名</param>
        /// <param name="message">消息内容</param>
        /// <returns></returns>
        long PublishNoneMessageId(string channel, string message);

        /// <summary>
        /// 将一个或多个值插入到列表头部
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value">一个或多个值</param>
        /// <returns>执行 LPUSH 命令后，列表的长度</returns>
        long LPush<T>(string key, params T[] value);

        /// <summary>
        /// 对一个列表进行修剪，让列表只保留指定区间内的元素，不在指定区间之内的元素都将被删除
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="start"> 开始位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <param name="stop">结束位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <returns></returns>
        bool LTrim<T>(string key, long start, long stop);

        /// <summary>
        /// 获取列表长度
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        long LLen(string key);

        /// <summary>
        /// 移出并获取列表的第一个元素
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        string LPop(string key);

        /// <summary>
        /// 移出并获取列表的第一个元素
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        T LPop<T>(string key);

        /// <summary>
        /// 移出并获取列表的最后一个元素
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        string RPop(string key);

        /// <summary>
        /// 移出并获取列表的最后一个元素
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        T RPop<T>(string key);

        /// <summary>
        /// 获取列表指定范围内的元素
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="start">开始位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <param name="stop"> 结束位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <returns></returns>
        string[] LRange(string key, long start, long stop);

        /// <summary>
        /// 获取列表指定范围内的元素
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="start">开始位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <param name="stop"> 结束位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <returns></returns>
        T[] LRange<T>(string key, long start, long stop);
        #endregion

        #region 异步操作
        /// <summary>
        /// 检查缓存Key是否存在
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        Task<bool> ContainsKeyAsync(string key);

        /// <summary>
        /// 批量删除缓存Key
        /// </summary>
        /// <param name="key"></param>
        /// <returns>删除成功的记录数量</returns>
        Task<bool> DeleteKeyAsync(string key);

        /// <summary>
        /// 批量删除缓存Key
        /// </summary>
        /// <param name="keys">key列表</param>
        /// <returns>删除成功的记录数量</returns>
        Task<bool> DeleteKeyAsync(params string[] keys);

        /// <summary>
        /// 重新命名key
        /// </summary>
        /// <param name="key">就的redis key</param>
        /// <param name="newKey">新的redis key</param>
        /// <returns></returns>
        Task<bool> RenameKeyAsync(string key, string newKey);

        /// <summary>
        /// 设置缓存过期
        /// </summary>
        /// <param name="key"></param>
        /// <param name="timeoutSeconds"></param>
        Task<bool> SetExpireAsync(string key, int timeoutSeconds);

        /// <summary>
        /// 获取String类型的缓存
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        Task<string> StringGetAsync(string key);

        /// <summary>
        /// 获取String类型的缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <returns></returns>
        Task<T> StringGetAsync<T>(string key);

        /// <summary>
        /// 设置String类型缓存
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expireSeconds"></param>
        /// <returns></returns>
        Task<bool> StringSetAsync(string key, object value, int expireSeconds = -1);

        /// <summary>
        /// 设置String类型缓存
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <param name="expireSeconds"></param>
        /// <returns></returns>
        Task<bool> StringSetAsync<T>(string key, T value, int expireSeconds = -1);

        /// <summary>
        /// 原子性递增
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value">增量：可以为负数</param>
        /// <param name="expireSeconds">缓存过期时间(单位：秒)</param>
        /// <returns>增长后的值</returns>
        Task<long> StringIncrementAsync(string key, long value = 1, int expireSeconds = -1);

        /// <summary>
        /// 检查hash键是否存在
        /// </summary>
        /// <param name="key"></param>
        /// <param name="hashField"></param>
        /// <returns></returns>
        Task<bool> ContainsHashKeyAsync(string key, string hashField);

        /// <summary>
        /// 移除hash中的某值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="hashField"></param>
        /// <returns></returns>
        Task<bool> DeleteHashAsync(string key, string hashField);

        /// <summary>
        /// 移除hash中的某值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="hashFields"></param>
        /// <returns></returns>
        Task<bool> DeleteHashAsync(string key, params string[] hashFields);

        /// <summary>
        /// 获取Hash值
        /// </summary>
        /// <param name="key"></param>
        /// <param name="hashField"></param>
        /// <returns></returns>
        Task<string> HashGetAsync(string key, string hashField);

        /// <summary>
        /// 获取Hash值
        /// </summary>
        /// <param name="key"></param>
        /// <param name="hashField"></param>
        /// <returns></returns>
        Task<T> HashGetAsync<T>(string key, string hashField);

        /// <summary>
        /// 设置缓存
        /// </summary>
        /// <param name="key"></param>
        /// <param name="hashField"></param>
        /// <param name="value"></param>
        /// <param name="timeoutSeconds"></param>
        /// <returns></returns>
        Task<bool> HashSetAsync(string key, string hashField, string value, int timeoutSeconds = -1);

        /// <summary>
        /// 设置缓存
        /// </summary>
        /// <param name="key"></param>
        /// <param name="hashField"></param>
        /// <param name="value"></param>
        /// <param name="timeoutSeconds"></param>
        /// <returns></returns>
        Task<bool> HashSetAsync<T>(string key, string hashField, T value, int timeoutSeconds = -1);

        /// <summary>
        /// 原子性递增
        /// </summary>
        /// <param name="key"></param>
        /// <param name="hashField"></param>
        /// <param name="value">增量：可以为负数</param>
        /// <param name="timeoutSeconds">缓存过期时间（单位：秒）</param>
        /// <returns>增长后的值</returns>
        Task<long> HashIncrementAsync(string key, string hashField, long value = 1, int timeoutSeconds = -1);

        /// <summary>
        /// 原子性递增
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value">增量：可以为负数</param>
        /// <returns>增长后的值</returns>
        Task<long> StringIncrementNoExpireAsync(string key, long value = 1);

        /// <summary>
        /// 原子性递增 绝对过期时间
        /// </summary>
        /// <param name="key"></param>
        /// <param name="value">增量：可以为负数</param>
        /// <param name="expireSeconds">过期时间</param>
        /// <returns>增长后的值</returns>
        Task<long> StringIncrementByAbsoluteExpireAsync(string key, long value = 1, int expireSeconds = -1);

        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <param name="timeoutSeconds"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        Task<bool> SetNxAsync(string key, object value, int timeoutSeconds);

        /// <summary>
        /// 消息发布
        /// </summary>
        /// <param name="channel">频道名</param>
        /// <param name="message">消息内容</param>
        /// <returns></returns>
        Task<long> PublishNoneMessageIdAsync(string channel, string message);

        /// <summary>
        /// 将一个或多个值插入到列表头部
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="value">一个或多个值</param>
        /// <returns>执行 LPUSH 命令后，列表的长度</returns>
        Task<long> LPushAsync<T>(string key, params T[] value);

        /// <summary>
        /// 对一个列表进行修剪，让列表只保留指定区间内的元素，不在指定区间之内的元素都将被删除
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="start"> 开始位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <param name="stop">结束位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <returns></returns>
        Task<bool> LTrimAsync<T>(string key, long start, long stop);

        /// <summary>
        /// 移出并获取列表的第一个元素
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        Task<string> LPopAsync(string key);

        /// <summary>
        /// 移出并获取列表的第一个元素
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        Task<T> LPopAsync<T>(string key);

        /// <summary>
        /// 移出并获取列表的最后一个元素
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        Task<string> RPopAsync(string key);

        /// <summary>
        /// 移出并获取列表的最后一个元素
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        Task<T> RPopAsync<T>(string key);

        /// <summary>
        /// 获取列表长度
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        Task<long> LLenAsync(string key);

        /// <summary>
        /// 获取列表指定范围内的元素
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="start">开始位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <param name="stop"> 结束位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <returns></returns>
        Task<string[]> LRangeAsync(string key, long start, long stop);

        /// <summary>
        /// 获取列表指定范围内的元素
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">不含prefix前辍</param>
        /// <param name="start">开始位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <param name="stop"> 结束位置，0表示第一个元素，-1表示最后一个元素</param>
        /// <returns></returns>
        Task<T[]> LRangeAsync<T>(string key, long start, long stop);
        #endregion
    }
}
